home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / umich / network / ka9q / nhclb120.zoo / dirutil.c < prev    next >
C/C++ Source or Header  |  1992-06-20  |  16KB  |  693 lines

  1. /* dirutil.c - MS-DOS directory reading routines
  2.  *
  3.  * Bdale Garbee, N3EUA, Dave Trulli, NN2Z, and Phil Karn, KA9Q
  4.  * Directory sorting by Mike Chepponis, K3MC
  5.  * adapted for ATARI ST & cleaned up by Rob Janssen, PE1CHL
  6.  * adapted for Lattice C by Walter Doerr, DG2KK
  7.  */
  8.  
  9. #include <stdio.h>
  10. static    void dir_sort(), format_dir(),format_fname(), diskfree(), free_clist();
  11. static getdir_nosort();
  12. static getdir();
  13.  
  14. #ifndef GNUC
  15. #define Fsetdta(a) bdos(SET_DTA,a)
  16. #endif
  17.  
  18. #ifndef LATTICE
  19. #include <ctype.h>        /* DG2KK: force Lattice to use library func. */
  20. #endif
  21.  
  22. #if defined( LATTICE ) || ( defined(ATARI_ST) && defined(GNUC))
  23. #define    S_IJHID        2
  24. #define S_IJSYS        4
  25. #define S_IJDIR        0x10
  26. struct stat {
  27.     char st_mode;            /* that's all we need */
  28. };    
  29.  
  30. #else                        /* not LATTICE */
  31.  
  32. #ifdef __TURBOC__
  33. #include <dos.h>
  34. #include <sys\stat.h>
  35. #else                        /* not LATTICE and not TURBOC */
  36. #include <stat.h>
  37. #endif
  38. #endif
  39.  
  40. #ifdef MSDOS
  41. #define  IS_ERROR    == -1        /* error return from MSDOS */
  42. #endif
  43.  
  44. #ifdef __TURBOC__
  45. #define ST_RDONLY    0x01        /* Read only attribute */
  46. #define ST_HIDDEN    0x02        /* Hidden file */
  47. #define ST_SYSTEM    0x04        /* System file */
  48. #define ST_LABEL    0x08        /* Volume label */
  49. #define ST_DIRECT    0x10        /* Directory */
  50. #define ST_ARCH        0x20        /* Archive */
  51.  
  52. int dos(unsigned ah,
  53.     unsigned bx,
  54.     unsigned cx,
  55.     void *dx,
  56.     unsigned si,
  57.     unsigned di)
  58. {
  59.     union REGS regs;
  60.  
  61.     regs.h.ah = ah;
  62.     regs.x.bx = bx;
  63.     regs.x.cx = cx;
  64.     regs.x.dx = dx;
  65.     regs.x.si = si;
  66.     regs.x.di = di;
  67.  
  68.     intdos(®s, ®s);
  69.  
  70.     if (regs.x.cflag) return -1;
  71.     return 0;
  72. }
  73.  
  74. #define bdos(x, y)    bdos(x, (unsigned) y, 0)
  75.  
  76. #endif  /* TURBOC */
  77.  
  78.  
  79. #ifdef ATARI_ST
  80. #define  IS_ERROR    < 0        /* error return from gemdos */
  81. #include <osbind.h>            /* os interface defines */
  82. #define  bdos        gemdos        /* Atari OS call */
  83. #ifndef GNUC
  84. #define  dos(a,b,c,d,e,f) gemdos(a,d,c) /* only valid for FIND func */
  85. #else
  86. #define  dos(a,b,c,d,e,f) gnudos(a,d,c)
  87. short gnudos();
  88. #endif
  89.  
  90. #define  st_attr    st_mode     /* what's in a name? */
  91. #define  ST_HIDDEN    S_IJHID     /* Hidden from search */
  92. #define  ST_SYSTEM    S_IJSYS     /* System, hidden from search */
  93. #define  ST_DIRECT    S_IJDIR     /* Directory */
  94. #endif
  95.  
  96. #include "global.h"
  97.  
  98. #ifndef FALSE
  99. #define FALSE    (0)
  100. #endif
  101.  
  102. #ifndef TRUE
  103. #define TRUE    !(FALSE)
  104. #endif
  105.  
  106. #define REGFILE (ST_HIDDEN|ST_SYSTEM|ST_DIRECT)
  107. #define SET_DTA     0x1a
  108. #define FIND_FIRST    0x4e
  109. #define FIND_NEXT    0x4f
  110.  
  111. struct dirent {
  112.     char rsvd[21];
  113.     char attr;
  114.     short ftime;
  115.     short fdate;
  116.     long fsize;
  117.     char fname[13];
  118. };
  119. #define NULLENT (struct dirent *)0
  120.  
  121. struct dirsort {
  122.     struct dirsort *prev;
  123.     struct dirsort *next;
  124.     struct dirent *direntry;
  125. };
  126. #define NULLSORT (struct dirsort *)0
  127.  
  128. /* Create a directory listing in a temp file and return the resulting file
  129.  * descriptor. If full == 1, give a full listing; else return just a list
  130.  * of names.
  131.  */
  132. FILE *
  133. dir(path,full)
  134. char *path;
  135. int full;
  136. {
  137.     FILE *fp,*tmpfile();
  138.  
  139.     if ((fp = tmpfile()) != NULLFILE)
  140.     {
  141.         getdir(path,full,fp);
  142.         /* This should be rewind(), but Aztec doesn't have it */
  143. #if    (ATARI_ST && MWC)
  144.         vseek(fp,0L,0);
  145. #else
  146.         fseek(fp,0L,0);
  147. #endif
  148.     }
  149.     return fp;
  150. }
  151.  
  152. /* wildcard filename lookup */
  153. filedir(name,times,ret_str)
  154. char *name;
  155. int times;
  156. char *ret_str;
  157. {
  158.     register char *cp,*cp1;
  159.     static struct dirent sbuf;
  160.  
  161.     Fsetdta(&sbuf);    /* Set disk transfer address */
  162.  
  163.     /* Find matching file */
  164.     if(dos(times == 0 ? FIND_FIRST:FIND_NEXT,0,REGFILE,name,0,0) IS_ERROR) 
  165.         sbuf.fname[0] = '\0';
  166.  
  167.     /* Copy result to output, forcing to lower case */
  168.     for(cp = ret_str,cp1 = sbuf.fname; cp1 < &sbuf.fname[13] && *cp1 != '\0';)
  169.         *cp++ = (char)tolower(*cp1++);    /* DG2KK: added (char) */
  170.     *cp = '\0';
  171. }
  172.  
  173. /* Change working directory */
  174. docd(argc,argv)
  175. int argc;
  176. char *argv[];
  177. {
  178.     char dirname[128];
  179. #ifdef MSDOS
  180.     char *getcwd();
  181. #endif
  182.  
  183.     if(argc > 1){
  184.         if(chdir(argv[1]) IS_ERROR){
  185.             printf("Can't change directory\n");
  186.             return 1;
  187.         }
  188.     }
  189.  
  190. #ifdef MSDOS
  191.     if(getcwd(dirname,0) != NULLCHAR){
  192.         printf("\\%s\n",dirname);
  193.     }
  194. #endif
  195. #ifdef ATARI_ST
  196.     if (Dgetpath(dirname,0) == 0){
  197.         printf("%c:%s%s\n",(char) Dgetdrv()+'A',
  198.             (*dirname? "" : "\\"),dirname);
  199.     }
  200. #endif
  201.     return 0;
  202. }
  203.  
  204. /* List directory to console. [-/]w option selects "wide" format */
  205. dodir(argc,argv)
  206. int argc;
  207. char *argv[];
  208. {
  209.     char *path;
  210.     int full = 1;
  211.  
  212.     if (argc > 1 &&
  213.         (argv[1][0] == '-' || argv[1][0] == '/') && argv[1][1] == 'w')
  214.     {
  215.         full = -1;
  216.         argv++;
  217.         argc--;
  218.     }
  219.  
  220.     if(argc >= 2){
  221.         path = argv[1];
  222.     } else {
  223.         path = "*.*";
  224.     }
  225.     getdir(path,full,stdout);
  226.     return 0;
  227. }
  228.  
  229. /* do a directory list to the stream 
  230.  * full = 0 -> short form, 1 is long, -1 is multi-column short
  231. */
  232. static
  233. getdir(path,full,file)
  234. char *path;
  235. int full;
  236. FILE *file;
  237. {
  238.     struct dirent sbuf;
  239.     struct stat statbuf;
  240.     char *cp,*cp1;                /* !!!!!!! was: register */
  241.     char dirtmp[20];
  242.     int command = FIND_FIRST;
  243.     int i = 0;
  244.     int cflag = 0;
  245.     int n = 0;
  246.     char line_buf[50];        /* for long dirlist */
  247.     
  248.     struct dirsort *head, *here, *new;
  249.     struct dirent *de;
  250.  
  251.     int malloc_lost = FALSE;
  252.  
  253.     /* Root directory is a special case */
  254.     if(path == NULLCHAR || *path == '\0' || strcmp(path,"\\") == 0)
  255.         path = "\\*.*";
  256.  
  257.     /* If arg is a directory, append "\*.*" to it.
  258.      * This is tricky, since the "stat" system call actually
  259.      * calls the DOS "find matching file" function. The stat
  260.      * call therefore returns the attributes for the first matching
  261.      * entry in the directory. If the arg already ends in *.*,
  262.      * stat will match the . entry in the directory and indicate
  263.      * that the argument is a valid directory name. Hence the
  264.      * heuristic check for '*' in the file name. Kludge...
  265.      */
  266. #ifdef __TURBOC__
  267.     else if(stat(path,&statbuf) != -1
  268.      && (statbuf.st_mode & S_IFDIR)
  269.      && index(path,'*') == NULLCHAR) {
  270. #else
  271.     else if(index(path,'*') == NULLCHAR
  272.      && stat(path,&statbuf) != -1
  273.      && (statbuf.st_attr & ST_DIRECT)) {
  274. #endif
  275.         if((cp = malloc(strlen(path) + 10)) == NULLCHAR)
  276.             return -1;
  277.         sprintf(cp,"%s%c%s",path,'\\',"*.*");
  278.         path = cp;
  279.         cflag = 1;
  280.     }
  281.     head = NULLSORT;    /* No head of chain yet... */
  282.     for(;;){
  283.         Fsetdta(&sbuf);    /* Set disk transfer address */
  284.         if(dos(command, 0, REGFILE, path, 0, 0) IS_ERROR)
  285.             break;
  286.  
  287.         command = FIND_NEXT;    /* Got first one already... */
  288.         if(sbuf.fname[0] != '.'){
  289.             /* nuke "." and ".." */
  290.             n++;    /* One more entry */
  291.             new = (struct dirsort *) malloc(sizeof(struct dirsort));
  292.             if(new == NULLSORT)
  293.                 malloc_lost = TRUE;
  294.             de  = (struct dirent *)malloc(sizeof(struct dirent));
  295.             if(de == NULLENT)
  296.                 malloc_lost = TRUE;
  297.             if(malloc_lost){
  298.                 /* Clean up and call other routine */
  299.                 if(new)free(new);
  300.                 free_clist(head);
  301.                 return getdir_nosort(path,full,file);
  302.             }
  303.             *de = sbuf;    /* Copy contents of directory entry struct */
  304.  
  305.             /* Fix up names for easier sorting... pain! */
  306.             strcpy(de->fname,"           ");    /* 11 blanks */
  307.             cp  = sbuf.fname;
  308.             cp1 = de->fname;
  309.  
  310.             do *cp1++ = *cp++; while (*cp && *cp != '.');
  311.  
  312.             if(*cp++){
  313.                 /* If there is an extension */
  314.                 cp1 = &(de->fname[8]);
  315.                 do *cp1++ = *cp++; while (*cp);
  316.             }
  317.             if(!(int)head){
  318.                 /* Make the first one */
  319.                 here = head = new;
  320.                 head->prev = head->next = NULLSORT;
  321.             } else {
  322.                 /* Link on next one */
  323.                 new->next = NULLSORT;
  324.                 new->prev = here;
  325.                 here->next = new;
  326.                 here = new;
  327.             }
  328.             new->direntry = de;
  329.         } /* IF on "." */
  330.     } /* infinite FOR loop */
  331.  
  332.     if(head)
  333.         dir_sort(head);     /* Make a nice, sorted list */
  334.  
  335.     here = head;
  336.     if(here)
  337.         if(full > 0){
  338.         do {
  339.             format_dir(line_buf,here->direntry);
  340.             fprintf(file,"%s%s",line_buf,(i^=1) ? "   " : "\r\n");
  341.         } while (here = here->next);
  342.         if(i & 1)
  343.             fprintf(file,"\r\n");
  344.         }
  345.         else {
  346.         /* This is the short form */
  347.         do {
  348.             format_fname(dirtmp,here->direntry->fname,
  349.                         here->direntry->attr);
  350.             fprintf(file,"%-15s%s",dirtmp,((full && ++i % 5)?"":"\r\n"));
  351.         } while (here = here->next);
  352.         if(full && i % 5)
  353.             fprintf(file,"\r\n");
  354.         }
  355.  
  356.     /* Give back all the memory we temporarily needed... */
  357.     free_clist(head);
  358.  
  359.     if(full > 0){
  360.         /* Provide additional information only on DIR */
  361.  
  362.         if (isalpha(*path) && path[1] == ':')    /* detect A: drivespec */
  363.             diskfree(file,*path & 0x1f,n);
  364.         else
  365.             diskfree(file,0,n);
  366.     }
  367.     if(cflag)
  368.         free(path);
  369.     return 0;
  370. } /* getdir */
  371.  
  372. static
  373. getdir_nosort(path,full,file)
  374. char *path;
  375. int